var SAVE_TYPE_DEFAULT = 0;
var SAVE_TYPE_REFRESH = 1;     //刷新
var SAVE_TYPE_SEED = 2;        //播种

exports.get = function(player, req, resp, onHandled) {
    do {
        if (!gConfSwitch.HoroscopeFarm) {
            resp.code = 1; resp.desc = "not open"; break;
        }

        var horoscopeFarm = player.getHoroscopeFarm();
        if (!horoscopeFarm) {
            resp.code = 1; resp.desc = "not init"; break;
        }

        resp.data.horoscope_farm = player.getHoroscopeFarm();
        resp.data.horoscopefarm_tree = gHoroscopefarmTree.getUserInfo(player.uid);
    } while (false);

    onHandled && onHandled();
}

exports.save = function(player, req, resp, onHandled) {
    var user = player.user;
    do {
        var type = +req.args.type || 0;
        var opFlow = req.args.opflow;

        if (!gConfSwitch.HoroscopeFarm) {
            resp.code = 1; resp.desc = "not open"; break;
        }

        var horoscopeFarm = player.getHoroscopeFarm();
        if (!horoscopeFarm) {
            resp.code = 1; resp.desc = "not init"; break;
        }

        var opFlowNotEmpty = true;
        if (!opFlow || !(opFlow instanceof Array) || opFlow.length == 0) {
            opFlowNotEmpty = false;
        }


        var store = horoscopeFarm.store;
        var land = horoscopeFarm.land;
        if (opFlowNotEmpty) {//判断操作流水是否正确
            try {
                store = clone(horoscopeFarm.store);
                land = clone(horoscopeFarm.land);

                for (var i = 0, max = opFlow.length; i < max; ++i) {
                    var operation = opFlow[i];
                    var value = +operation.value || 0;

                    if ('add' == operation.action) {//从商店添加到购物车(land中seed不为0但stamp为0)
                        //从商店里标记此物品已被购被
                        if (value >= store.length) {
                            resp.code = 1; resp.desc = "invalid add value"; break;
                        }
                        
                        var storeItem = store[value];
                        if (storeItem.status) {
                            resp.code = 1; resp.desc = "add purchased"; break;
                        }
                        storeItem.status = 1;

                        //将种子添加到购物车中
                        var existIdleland = false;
                        for (var landIdx = 0, landLength = land.length; landIdx < landLength; ++landIdx) {
                            var landItem = land[landIdx];
                            if (!landItem.seed) {
                                landItem.seed = storeItem.seed;
                                existIdleland = true;
                                break;
                            }
                        }

                        if (!existIdleland) {
                            resp.code = 1; resp.desc = "no idle land"; break;
                        }
                    } else if ('del' == operation.action) {//从购物车里删除
                        if (value >= land.length) {
                            resp.code = 1; resp.desc = "invalid del value"; break;
                        }
                        
                        var landItem = land[value];
                        if (!landItem.seed) {
                            resp.code = 1; resp.desc = "del no seed"; break;
                        }

                        if (landItem.stamp) {
                            resp.code = 1; resp.desc = "del not shopping"; break;
                        }

                        landItem.seed = 0;
                    } else {
                        resp.code = 1; resp.desc = "invalid action"; break;
                    }
                }
            } catch (e) {
                resp.code = 1; resp.desc = "opflow exception"; break;
            }

            if (resp.code) {
                break;
            }
        }
        
        if (SAVE_TYPE_REFRESH == type) {//判断刷新是否满足条件
            var todayRefreshTime = player.getDailyVar('horoscopefarm_refresh');
            if (todayRefreshTime >= gConfGlobal.HoroscopeFarmRefreshFreeTimes) {
                var confBuy = gConfBuy[todayRefreshTime - gConfGlobal.HoroscopeFarmRefreshFreeTimes + 1];
                if (!confBuy || !confBuy.HoroscopeFarmRefresh) {
                    resp.code = 1; resp.desc = "no refresh times"; break;
                }

                var costCash = confBuy.HoroscopeFarmRefresh;
                if (!player.costResource('cash', costCash, todayRefreshTime)) {
                    resp.code = 1; resp.desc = "lack of cash"; break;
                }
                resp.data.cash = -costCash;
            }
            player.addDailyVar('horoscopefarm_refresh', 1);
        } else if (SAVE_TYPE_SEED == type) {//判断播种是否满足条件
            var costScore = 0;
            for (var landIdx = 0, landLength = land.length; landIdx < landLength; ++landIdx) {
                var landItem = land[landIdx];
                if (landItem.seed && !landItem.stamp) {
                    costScore += gConfHoroscopeSeed[landItem.seed].Score;
                }
            }

            if (costScore > horoscopeFarm.score) {
                resp.code = 1; resp.desc = "lack of score"; break;
            }
            horoscopeFarm.score -= costScore;
            player.markDirty('horoscope_farm.score');
            resp.data.score = -costScore;
        }
        
        if (opFlowNotEmpty) {//存操作流水引起的变化
            horoscopeFarm.store = store;
            horoscopeFarm.land = land;
            player.markDirty('horoscope_farm.store');
            player.markDirty('horoscope_farm.land');
            resp.data.store = horoscopeFarm.store;
            resp.data.land = horoscopeFarm.land;
        }

        if (SAVE_TYPE_REFRESH == type) {
            player.refreshHoroscopeFarmStore();
            resp.data.store = horoscopeFarm.store;
        } else if (SAVE_TYPE_SEED == type) {
            var nowStamp = Date.getStamp();
            for (var landIdx = 0, landLength = land.length; landIdx < landLength; ++landIdx) {
                var landItem = land[landIdx];
                if (landItem.seed && !landItem.stamp) {
                    landItem.stamp = nowStamp;
                }
            }
            player.markDirty('horoscope_farm.land');
            resp.data.land = horoscopeFarm.land;
        }
    } while (false);

    onHandled && onHandled();
}

exports.exchange_score = function(player, req, resp, onHandled) {
    do {
        if (!gConfSwitch.HoroscopeFarm) {
            resp.code = 1; resp.desc = "not open"; break;
        }

        var horoscopeFarm = player.getHoroscopeFarm();
        if (!horoscopeFarm) {
            resp.code = 1; resp.desc = "not init"; break;
        }

        if (isNaN(req.args.id) || isNaN(req.args.num)) {
            resp.code = 1; resp.desc = "invalid args"; break;
        }

        var id = parseInt(req.args.id);
        var num = parseInt(req.args.num);
        if (num <=0 || num >= 1000) {
            resp.code = 1; resp.desc = "invalid num"; break;
        }

        var exchangeConf = gConfHoroscopeExchange[id];
        if (!exchangeConf) {
            resp.code = 1; resp.desc = "invalid id"; break;
        }
        
        var costs = exchangeConf.Costs;
        if (num > 1) {
            costs = clone(costs);
            costs.forEach(function(cost) {
                cost[cost.length - 1] = cost[cost.length - 1] * num;
            });
        }

        costs = player.addCosts(costs);
        if (0 == costs.length) {
            resp.code = 1; resp.desc = 'cost not enough'; break;
        }
        
        var addScore = exchangeConf.Score*num;
        horoscopeFarm.score += addScore;
        player.markDirty('horoscope_farm.score');
        resp.data.score = addScore;
        resp.data.costs = costs;
    } while (false);

    onHandled && onHandled();
}

exports.harvest = function(player, req, resp, onHandled) {
    do {
        if (!gConfSwitch.HoroscopeFarm) {
            resp.code = 1; resp.desc = "not open"; break;
        }

        var horoscopeFarm = player.getHoroscopeFarm();
        if (!horoscopeFarm) {
            resp.code = 1; resp.desc = "not init"; break;
        }

        if (isNaN(req.args.id)) {
            resp.code = 1; resp.desc = "invalid args"; break;
        }
        
        var land = horoscopeFarm.land;
        var id = parseInt(req.args.id);
        if (id < 0 || id >= land.length) {
            resp.code = 1; resp.desc = "invalid id"; break;
        }

        var landItem = land[id];
        if (!landItem.seed || !landItem.stamp) {
            resp.code = 1; resp.desc = "not seed"; break;
        }

        var nowStamp = Date.getStamp();
        var seedConf = gConfHoroscopeSeed[landItem.seed];
        if ((Date.getStamp() - landItem.stamp + 10) < seedConf.RipeTime) {
            resp.code = 1; resp.desc = "not riped"; break;
        }

        var awards = seedConf.Awards;
        if (landItem.water > 0) {
            awards = clone(awards);
            awards.forEach(function(awards) {
                awards[awards.length - 1] += Math.floor(awards[awards.length - 1] * landItem.water * gConfGlobal.HoroscopeFarmWaterAddition / 100);
            });
        }
        resp.data.awards = player.addAwards(awards);
        
        landItem.seed = 0;
        landItem.stamp = 0;
        landItem.water = 0;
        player.markDirty('horoscope_farm.land');
    } while (false);

    onHandled && onHandled();
}

exports.buy_land = function(player, req, resp, onHandled) {
    var user = player.user;

    do {
        if (!gConfSwitch.HoroscopeFarm) {
            resp.code = 1; resp.desc = "not open"; break;
        }

        var horoscopeFarm = player.getHoroscopeFarm();
        if (!horoscopeFarm) {
            resp.code = 1; resp.desc = "not init"; break;
        }

        var land = horoscopeFarm.land;
        if (land.length >= Object.keys(gConfHoroscopeLand).length) {
            resp.code = 1; resp.desc = "no empty land"; break;
        }

        var landConf = gConfHoroscopeLand[land.length + 1];
        if (user.status.level < landConf.OpenLevel) {
            resp.code = 1; resp.desc = "level limit"; break;
        }

        var costs = player.addCosts(landConf.Costs);
        if (0 == costs.length) {
            resp.code = 1; resp.desc = 'cost not enough'; break;
        }
        
        land.push({seed:0, stamp:0, water:0});
        player.markDirty('horoscope_farm.land');
        resp.data.costs = costs;
        resp.data.land = land;
    } while (false);

    onHandled && onHandled();
}

exports.water = function(player, req, resp, onHandled) {
    do {
        if (!gConfSwitch.HoroscopeFarm) {
            resp.code = 1; resp.desc = "not open"; break;
        }

        var horoscopeFarm = player.getHoroscopeFarm();
        if (!horoscopeFarm) {
            resp.code = 1; resp.desc = "not init"; break;
        }

        if (isNaN(req.args.id)) {
            resp.code = 1; resp.desc = "invalid args"; break;
        }
        
        var land = horoscopeFarm.land;
        var id = parseInt(req.args.id);
        if (id < 0 || id >= land.length) {
            resp.code = 1; resp.desc = "invalid id"; break;
        }

        var landItem = land[id];
        if (!landItem.seed || !landItem.stamp) {
            resp.code = 1; resp.desc = "not seed"; break;
        }

        var buyConf = gConfBuy[landItem.water + 1];
        if (!buyConf || !buyConf.HoroscopeFarmWater) {
            resp.code = 1; resp.desc = "water limit"; break;
        }

        var seedConf = gConfHoroscopeSeed[landItem.seed];
        var costCash = Math.floor(seedConf.WaterCost * buyConf.HoroscopeFarmWater/100);
        if (!player.costResource('cash', costCash, id, landItem.water)) {
            resp.code = 1; resp.desc = "lack of cash"; break;
        }

        landItem.water++;
        player.markDirty('horoscope_farm.land');
        resp.data.cash = -costCash;
    } while (false);

    onHandled && onHandled();
}

exports.get_friend_tree = function(player, req, resp, onHandled) {
    var user = player.user;
    do {
        var level = user.status.level;
        if (level <= gConfRuntime.HoroscopeFarmTreeAssistTimes) {
            resp.code = 1; resp.desc = "level limit"; break;
        }

        if (isNaN(req.args.uid)) {
            resp.code = 1; resp.desc = "invalid args"; break;
        }

        var uid = +req.args.uid;
        var friendInfo = gUserInfo.getUser(uid);
        if (!friendInfo) {
            resp.code = 1; resp.desc = "invalid user"; break;
        }

        if (friendInfo.level < gConfGlobal.HoroscopeFarmOpenLevel) {
            resp.code = 1; resp.desc = "level limit"; break;
        }

        gDBUser.findOne({_id: uid}, {'horoscope_farm':1}, function(err, doc){
            do {
                if (err || !doc) {
                    resp.code = 1; resp.desc = 'no data'; break;
                }
                
                var friendFarm = doc.horoscope_farm;
                resp.data.land = friendFarm ? friendFarm.land : [];
                resp.data.horoscopefarm_tree = gHoroscopefarmTree.getUserInfo(uid);
            } while(false);

            onHandled();
        });
        return;
    } while (false);

    onHandled && onHandled();
}

exports.assist_friend_tree = function(player, req, resp, onHandled) {
    var user = player.user;
    do {
        var level = user.status.level;
        if (level <= gConfRuntime.HoroscopeFarmTreeAssistTimes) {
            resp.code = 1; resp.desc = "level limit"; break;
        }

        if (isNaN(req.args.uid)) {
            resp.code = 1; resp.desc = "invalid args"; break;
        }

        var horoscopeFarm = player.getHoroscopeFarm();
        if (!horoscopeFarm) {
            resp.code = 1; resp.desc = "not init"; break;
        }

        var uid = +req.args.uid;
        var friendInfo = gUserInfo.getUser(uid);
        if (!friendInfo) {
            resp.code = 1; resp.desc = "invalid user"; break;
        }

        if (friendInfo.level < gConfGlobal.HoroscopeFarmOpenLevel) {
            resp.code = 1; resp.desc = "level limit"; break;
        }

        if (assistTimes >= gConfRuntime.HoroscopeFarmTreeAssistTimes) {
            resp.code = 1; resp.desc = "times limit"; break;
        }

        if (!gHoroscopefarmTree.assist(player.uid, uid)) {
            resp.data.code = 101; break;
        }

        var score = 0;
        var point = 0;
        var assistTimes = player.addDailyVar('horoscopefarm_tree_assist_times', 1);
        if (1 == assistTimes) {
            var conf = null;
            for (var Id in gConfHoroscopeFarmTreeAward) {
                conf = gConfHoroscopeFarmTreeAward[Id];
                if (level <= conf.Level) {
                    break;
                }
            }

            var oldPoint = player.user.status.friend_point || 0;
            point = player.addFriendPoint(+conf.Point) - oldPoint;
            if (point > 0) {
                score = +conf.Score;
                horoscopeFarm.score += score;
                player.markDirty('horoscope_farm.score');
            }
        }

        resp.data.horoscopefarm_tree = gHoroscopefarmTree.getUserInfo(uid);
        resp.data.score = score;
        resp.data.point = point;
    } while (false);
    onHandled && onHandled();
}

exports.tree_award = function(player, req, resp, onHandled) {
    var user = player.user;
    var uid = player.uid;
    do {
        var level = user.status.level;
        if (level <= gConfRuntime.HoroscopeFarmTreeAssistTimes) {
            resp.code = 1; resp.desc = "level limit"; break;
        }

        var horoscopeFarm = player.getHoroscopeFarm();
        if (!horoscopeFarm) {
            resp.code = 1; resp.desc = "not init"; break;
        }
        
        if (!gHoroscopefarmTree.getAward(uid)) {
            resp.code = 1; resp.desc = "can not award"; break;
        }

        var score = +gConfGlobal.HoroscopeFarmTreeAwardScore;
        horoscopeFarm.score += score;
        player.markDirty('horoscope_farm.score');

        resp.data.horoscopefarm_tree = gHoroscopefarmTree.getUserInfo(uid);
        resp.data.score = score;
    } while (false);
    onHandled && onHandled();
}
